﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using WaterRegimenMonitor.Web.Models.Common;
using WaterRegimenMonitor.Web.DataModel;
using WaterRegimenMonitor.Web.Code;
using System.Data;

namespace WaterRegimenMonitor.Web.Domain
{
    /// <summary>
    /// 组织结构辅助类。
    /// </summary>
    public class OrganizationHelper
    {
        static OrganizationHelper()
        {
        }

        /// <summary>
        /// 组织结构缓存键值
        /// </summary>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2012/03/14 17:13    创建
        /// </history>
        public const string ORGANIZATION_CACHE_KEY = "CACHE_ORGANIZATION";

        /// <summary>
        /// 获得组织结构列表。
        /// </summary>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2012/03/14 17:03    创建
        /// </history>
        private static IList<Organization> OrganizationList
        {
            get
            {
                //获得缓存的组织结构列表
                IList<Organization> organizations = HttpContext.Current.Cache.Get(ORGANIZATION_CACHE_KEY) as IList<Organization>;

                //判断缓存是否存在
                if (null == organizations)
                {
                    //获得组织结构列表
                    using (TalimuEntities context = new TalimuEntities())
                    {
                        //查询组织结构列表
                        organizations = context.Organization.OrderBy(item => item.TheOrder).ToArray();
                    }

                    //添加到缓存
                    HttpContext.Current.Cache.Add(ORGANIZATION_CACHE_KEY, organizations, null, DateTime.MaxValue, TimeSpan.Zero, System.Web.Caching.CacheItemPriority.Normal, null);
                }

                //返回组织结构
                return organizations;
            }
        }

        public static Organization GetOrganizationByID(Guid? Organization_ID)
        {
            if (!Organization_ID.HasValue)
                return null;

            using (var context = new TalimuEntities())
            {
                return context.Organization.FirstOrDefault(organization => organization.Organization_ID == Organization_ID.Value);
            }
        }

        public static List<Organization> GetOrganizationList()
        {
            using (var context = new TalimuEntities())
            {
                return context.Organization.OrderBy(item => item.TheOrder).ToList();
            }
        }

        public static List<Organization> GetOrganizationList(Guid? parentID)
        {
            //用于保存结果
            List<Organization> result = new List<Organization>();

            //查询数据
            using (TalimuEntities context = new TalimuEntities())
            {
                //判断是否指定了父节点
                if (parentID.HasValue)
                {
                    //获得父节点
                    Organization parent = context.Organization.FirstOrDefault(item => item.Organization_ID == parentID);

                    //判断是否存在
                    if (null != parent)
                    {
                        //添加父节点
                        result.Add(parent);
                    }
                }

                OrganizationHelper.GetChildren(parentID, context.Organization, result);
            }

            //返回结果
            return result;
        }

        public static IEnumerable<TreeNodeData> QueryOrganizationTree()
        {
            using (var context = new TalimuEntities())
            {
                return GetChildren(null, context.Organization.ToList());
            }
        }

        public static IEnumerable<CheckTreeNode> QueryOrganizationCheckTree(Organization parent)
        {
            using (var context = new TalimuEntities())
            {
                //创建根节点
                CheckTreeNode root = new CheckTreeNode()
                {
                    id = parent.Organization_ID,
                    expanded = true,
                    leaf = false,
                    text = string.Format("{0} {1}", parent.Organization_Code, parent.Organization_Name),
                    @checked = false,
                    parentID = null,
                    data = GetCheckTreeNode(parent.Organization_ID, context.Organization.ToList())
                };

                //返回结果
                return new CheckTreeNode[] { root };
            }
        }

        private static IEnumerable<CheckTreeNode> GetCheckTreeNode(Guid parentID, IEnumerable<Organization> organizationList)
        {
            var children = from item in organizationList
                           where item.ParentID == parentID
                           orderby item.Organization_Code
                           select new CheckTreeNode
                           {
                               id = item.Organization_ID,
                               expanded = true,
                               leaf = item.IsLeaf,
                               text = string.Format("{0} {1}", item.Organization_Code, item.Organization_Name),
                               @checked = false,
                               parentID = item.ParentID,
                               data = GetCheckTreeNode(item.Organization_ID, organizationList)
                           };

            return children;
        }

        private static void GetChildren(Guid? parentID, IEnumerable<Organization> organizationList, List<Organization> result)
        {
            var children = (from organization in organizationList
                            where organization.ParentID == parentID
                            orderby organization.Organization_Code
                            select organization);

            result.AddRange(children);

            foreach (var organization in children)
            {
                GetChildren(organization.Organization_ID, organizationList, result);
            }
        }

        private static void GetChildren(Guid? parentID, IEnumerable<Organization> organizationList, List<Guid> result)
        {
            var children = (from organization in organizationList
                            where organization.ParentID == parentID
                            orderby organization.Organization_Code
                            select organization.Organization_ID);

            result.AddRange(children);

            foreach (var organization in children)
            {
                GetChildren(organization, organizationList, result);
            }
        }

        private static IEnumerable<TreeNodeData> GetChildren(Guid? parentID, IEnumerable<Organization> organizationList)
        {
            var children = from organization in organizationList
                           where organization.ParentID == parentID
                           orderby organization.Organization_Code
                           select
                               new TreeNodeData
                               {
                                   id = organization.Organization_ID,
                                   expanded = false,
                                   leaf = organization.IsLeaf,
                                   name = organization.Organization_Name,
                                   parentID = organization.ParentID,
                                   code = organization.Organization_Code,
                                   categoryName = string.Empty,
                                   data = GetChildren(organization.Organization_ID, organizationList)
                               };

            return children;
        }

        public static Organization GetOrganizationByID(Guid id)
        {
            using (var context = new TalimuEntities())
            {
                return context.Organization.FirstOrDefault(organization => organization.Organization_ID == id);
            }
        }

        public static DeleteResult DeleteOrganization(Guid id)
        {
            using (var context = new TalimuEntities())
            {
                var organization = context.Organization.FirstOrDefault(item => item.Organization_ID == id);
                if (organization == null || !organization.IsLeaf)
                    return DeleteResult.Ok;

                //just delete the leaf node.
                if (organization.ParentID.HasValue)
                {
                    var brothers = context.Organization.Where(item => item.ParentID == organization.ParentID).ToList();
                    if (brothers.Count <= 1)
                    {
                        var parent = context.Organization.FirstOrDefault(item => item.Organization_ID == organization.ParentID.Value);
                        if (parent != null)
                            parent.IsLeaf = true;
                    }
                }

                context.ObjectStateManager.ChangeObjectState(organization, EntityState.Deleted);
                try
                {
                    context.SaveChanges();
                }
                catch (UpdateException)
                {
                    return DeleteResult.UsingError;
                }
                return DeleteResult.Ok;
            }
        }

        public static void UpdateOrganization(TreeNodeData data)
        {
            using (var context = new TalimuEntities())
            {
                var organization = context.Organization.FirstOrDefault(item => item.Organization_ID == data.id);
                if (organization == null)
                    return;

                organization.Organization_Name = data.name;
                organization.Organization_Code = data.code;

                context.SaveChanges();
            }
        }

        public static Organization GetOrganizationByName(string name)
        {
            using (var context = new TalimuEntities())
            {
                return context.Organization.FirstOrDefault(organization => organization.Organization_Name == name);
            }
        }

        public static Organization GetOrganizationByCode(string code)
        {
            using (var context = new TalimuEntities())
            {
                return context.Organization.FirstOrDefault(organization => organization.Organization_Code == code);
            }
        }

        public static void CreateOrganization(TreeNodeData data)
        {
            using (var context = new TalimuEntities())
            {
                var organization = new Organization();

                organization.Organization_ID = Guid.NewGuid();
                organization.ParentID = data.parentID;
                organization.Organization_Name = data.name;
                organization.Organization_Code = data.code;
                organization.TheOrder = 0;
                organization.IsLeaf = true;

                if (data.parentID.HasValue)
                {
                    var parent = context.Organization.FirstOrDefault(item => item.Organization_ID == data.parentID.Value);
                    parent.IsLeaf = false;
                }

                context.AddToOrganization(organization);
                context.SaveChanges();
            }
        }

        public static readonly Guid DistrictOrganization = Guid.Parse("D1097D58-178A-458E-96DF-E8D0CD98027C");

        public static bool IsDistrictOrganization(Guid Organization_ID)
        {
            return Organization_ID == DistrictOrganization;
        }
    }
}